//
//  AddressBookHelper.m
//  Xiaoqian
//
//  Created by tgf on 13-1-27.
//  Copyright (c) 2013年 tgf. All rights reserved.
//

#import "AddressBookHelper.h"
#import <AddressBook/AddressBook.h>
#import "pinyin.h"

@implementation AddressBookHelper

@synthesize delegate = _delegate;

+ (BOOL)isMobileLike:(NSString *)string {
	return string.length == 11 && [string characterAtIndex:0] == '1';
}

+ (BOOL)isEmailLike:(NSString *)string {
	NSRange range = [string rangeOfString:@"@"];
	return range.length > 0;
}

+ (NSString *)getDigits:(NSString *)string {
	NSMutableString *ret = [NSMutableString string];
	const char *cstr = [string UTF8String];
	while (*cstr) {
		if (*cstr >= '0' && *cstr <= '9') {
			[ret appendFormat:@"%c", *cstr];
		}
		cstr++;
	}
	return [ret copy];
}

+ (NSString *)formatMobile:(NSString *)string {
	if (string.length != 11) {
		return string;
	}
	NSMutableString *ret = [string mutableCopy];
	[ret insertString:@" " atIndex:7];
	[ret insertString:@" " atIndex:3];
	return [ret copy];
}

+ (NSArray *)groupContacts:(NSArray *)contacts {
	NSMutableDictionary *firstLetterDict = [NSMutableDictionary dictionary];
	
	for (NSDictionary *person in contacts) {
		NSString *name = [NSString stringWithFormat:@"%@ %@", [person valueForKey:@"firstName"], [person valueForKey:@"lastName"]];
		name = [name stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" "]];
		if (!name.length) {
			continue;
		}
		
		NSString *email = @"";
		NSArray *emails = [person valueForKey:@"emails"];
		if (emails.count > 0) {
			email = [(NSArray *)[emails objectAtIndex:0] lastObject];
		}
		
		NSString *mobile = @"";
		NSArray *phoneNumbers = [person valueForKey:@"phoneNumbers"];
		int i = 0;
		for (NSArray *array in phoneNumbers) {
			NSString *number = [array lastObject];
			NSString *digits = [self getDigits:number];
			if (i++ == 0){
				mobile = digits.length > 0 ? digits : number;
			}
			if ([self isMobileLike:digits]) {
				mobile = digits;
				break;
			}
		}
		
		unsigned short firstChar = [name characterAtIndex:0];
		if (firstChar > 255) {
			firstChar = pinyinFirstLetter(firstChar);
		}
		NSString *firstLetter = [NSString stringWithFormat:@"%c", toupper(firstChar)];
		
		NSMutableDictionary *info = [@{@"name": name, @"mobile": mobile, @"email": email} mutableCopy];
		id tmp;
		if ((tmp = [person valueForKey:@"photo"])) {
			[info setValue:tmp forKey:@"photo"];
		}
		if ((tmp = [person valueForKey:@"public"])) {
			[info setValue:tmp forKey:@"public"];
		}
		
		NSMutableArray *array = [firstLetterDict valueForKey:firstLetter];
		if (!array) {
			array = [NSMutableArray array];
			[firstLetterDict setValue:array forKey:firstLetter];
		}
		[array addObject:info];
	}
	
	NSMutableArray *result = [NSMutableArray array];
	NSArray *keys = [[firstLetterDict allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString * obj1, NSString * obj2) {
		return [obj1 compare:obj2];
	}];
	for (NSString *key in keys) {
		NSArray *array = [firstLetterDict valueForKey:key];
		array = [array copy];
		[result addObject:@[key, array]];
	}
	return [result copy];
}

- (BOOL)isABAddressBookCreateWithOptionsAvailable {
    return &ABAddressBookCreateWithOptions != NULL;
}

- (void)loadContacts {
    ABAddressBookRef addressBook;
    if ([self isABAddressBookCreateWithOptionsAvailable]) {
        CFErrorRef error = nil;
        addressBook = ABAddressBookCreateWithOptions(NULL, &error);
        ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
            // callback can occur in background, address book must be accessed on thread it was created on
            dispatch_async(dispatch_get_main_queue(), ^{
                if (error) {
					if ([self.delegate respondsToSelector:@selector(addressBookHelperError:)]) {
						[self.delegate addressBookHelperError:self];
					}
                } else if (!granted) {
					if ([self.delegate respondsToSelector:@selector(addressBookHelperDeniedAcess:)]) {
						[self.delegate addressBookHelperDeniedAcess:self];
					}
                } else {
					[self loadContactsIntoArray:addressBook];
					CFRelease(addressBook);
                }
            });
        });
    } else {
        // iOS 4/5
        addressBook = ABAddressBookCreate();
		[self loadContactsIntoArray:addressBook];
        CFRelease(addressBook);
    }
}

- (NSArray *)loadMultiValue:(ABMultiValueRef)multiValue {
	NSMutableArray *array = [NSMutableArray array];
	for (CFIndex i = 0, n = ABMultiValueGetCount(multiValue); i < n; i++) {
		NSString *value = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(multiValue, i));
		NSString *label = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(multiValue, i));
		[array addObject:@[label ? label : @"", value ? value: @""]];
	}
	return [array copy];
}

- (void)loadContactsIntoArray:(ABAddressBookRef)addressBook {
	ABAddressBookRevert(addressBook);
    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
    
	CFMutableArrayRef peopleMutable = CFArrayCreateMutableCopy(
															   kCFAllocatorDefault,
															   CFArrayGetCount(people),
															   people
															   );
	
	CFArraySortValues(
					  peopleMutable,
					  CFRangeMake(0, CFArrayGetCount(peopleMutable)),
					  (CFComparatorFunction)ABPersonComparePeopleByName,
					  (void *)ABPersonGetSortOrdering()
					  );
	
	NSMutableArray *contacts = [NSMutableArray array];
	NSArray *emptyArray = [NSArray array];
	NSString *emptyString = @"";
	
	for (int i = 0, n = CFArrayGetCount(people); i < n; i++) {
		ABRecordRef person = CFArrayGetValueAtIndex(peopleMutable, i);
		NSString *firstName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
		NSString *lastName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
		NSArray *phoneNumbers = [self loadMultiValue:ABRecordCopyValue(person, kABPersonPhoneProperty)];
		NSArray *emails = [self loadMultiValue:ABRecordCopyValue(person, kABPersonEmailProperty)];
		[contacts addObject:@{
		 @"firstName": firstName ? firstName : emptyString,
		 @"lastName": lastName ? lastName : emptyString,
		 @"phoneNumbers": phoneNumbers ? phoneNumbers : emptyArray,
		 @"emails": emails ? emails : emptyArray,
		 }];
	}
	
	CFRelease(people);
	CFRelease(peopleMutable);

    [self.delegate addressBookHelper:self finishedLoading:contacts];
}

@end
